package com.github.jsoncat.server;

import com.github.jsoncat.common.constant.SystemConstants;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpRequestDecoder;
import io.netty.handler.codec.http.HttpResponseEncoder;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import lombok.extern.slf4j.Slf4j;

@Slf4j
public class HttpServer {

    private static final int PORT = 7080;

    public void start() {
        EventLoopGroup bossGroup = new NioEventLoopGroup(1);
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        DefaultEventLoopGroup controllerExecutors = new DefaultEventLoopGroup();
        try {
            ServerBootstrap b = new ServerBootstrap();
            b.group(bossGroup, workerGroup)
                    .channel(NioServerSocketChannel.class)
                    // TCP默认开启了 Nagle 算法，该算法的作用是尽可能的发送大数据快，减少网络传输。TCP_NODELAY 参数的作用就是控制是否启用 Nagle 算法。
                    .childOption(ChannelOption.TCP_NODELAY, true)
                    // 是否开启 TCP 底层心跳机制
                    .childOption(ChannelOption.SO_KEEPALIVE, true)
                    //表示系统用于临时存放已完成三次握手的请求的队列的最大长度,如果连接建立频繁，服务器处理创建新连接较慢，可以适当调大这个参数
                    .option(ChannelOption.SO_BACKLOG, 128)
                    .handler(new LoggingHandler(LogLevel.INFO))
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel ch) {
                            ch.pipeline().addLast("decoder", new HttpRequestDecoder())
                                    .addLast("encoder", new HttpResponseEncoder())
                                    .addLast("aggregator", new HttpObjectAggregator(512 * 1024))
                                    .addLast(controllerExecutors,"handler", new HttpServerHandler());
                    /*
                    这段Java代码配置了一个Netty服务器的ChannelPipeline，用于处理HTTP请求和响应。具体解释如下：

                    - `ch.pipeline()`：获取当前Channel的ChannelPipeline对象。ChannelPipeline是Netty中用于处理入站和出站事件的容器，它包含了一系列
                    的ChannelHandler。

                    - `.addLast("decoder", new HttpRequestDecoder())`：
                      - 添加一个名为`decoder`的`HttpRequestDecoder`处理器到管道的末尾。
                      - `HttpRequestDecoder`是一个解码器，用于将接收到的字节数据解析成HTTP请求对象（`HttpRequest`）。

                    - `.addLast("encoder", new HttpResponseEncoder())`：
                      - 添加一个名为`encoder`的`HttpResponseEncoder`处理器到管道的末尾。
                      - `HttpResponseEncoder`是一个编码器，用于将HTTP响应对象（`HttpResponse`）编码成字节数据，以便发送给客户端。

                    - `.addLast("aggregator", new HttpObjectAggregator(512 * 1024))`：
                      - 添加一个名为`aggregator`的`HttpObjectAggregator`处理器到管道的末尾。
                      - `HttpObjectAggregator`用于聚合HTTP消息片段（如HTTP请求体的多个部分）成一个完整的HTTP消息对象。参数`512 * 1024`指定了最大聚合内容
                      长度为512KB。

                    - `.addLast("handler", new HttpServerHandler())`：
                      - 添加一个名为`handler`的自定义`HttpServerHandler`处理器到管道的末尾。
                      - `HttpServerHandler`是一个自定义的业务逻辑处理器，用于处理具体的HTTP请求和响应。

                    总结：
                    - 这段代码通过在ChannelPipeline中添加一系列处理器，实现了对HTTP请求的解码、编码、聚合以及业务逻辑处理。这些处理器按顺序处理入站和出站事件，
                    确保了HTTP请求和响应的正确处理。
                     */
                        }
                    });
            Channel ch = b.bind(PORT).sync().channel();
            log.info(SystemConstants.LOG_PORT_BANNER, PORT);
            ch.closeFuture().sync();
        } catch (InterruptedException e) {
            log.error("occur exception when start server:", e);
        } finally {
            log.error("shutdown bossGroup and workerGroup");
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }
}
